package com.rt.cloud.auth.controller;

import cn.hutool.core.util.IdUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.rt.easyjava.base.biz1.dto.TmptAuthUserBizDto;
import com.rt.easyjava.base.biz1.service.impl.TmptAuthUserBizServiceImpl;
import com.rt.easyjava.common.base.Result;
import com.rt.easyjava.common.utils.others.DateTool;
import com.rt.easyjava.common.utils.others.StringUtils;
import com.rt.tmpt.dto.A2UserDto;
import com.rt.tmpt.service.IMenuService;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.omg.CORBA.portable.ApplicationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.core.io.ClassPathResource;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.provider.endpoint.TokenEndpoint;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.security.KeyPair;
import java.time.Instant;
import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@RestController
@RequestMapping("/oauth/token")
public class SSOApiService {

  @Autowired
  private RestTemplate restTemplate;
  @Resource
  private IMenuService menuService;

  @Value("${dtsso-security.oauth2.client.client-id:7eec9a9d9fa1498096c9ea8b375f32ab}")
  private String clientId;
  @Value("${dtsso-security.oauth2.client.client-secret:e4f977ec22b04340be4ed468fdd6cc5c}")
  private String clientSecret;
  @Value("${dtsso-security.oauth2.sso.redirect-login-uri}")
  private String redirectUri;
  @Value("${dtsso-security.oauth2.client.access-token-uri}")
  private String accessTokenUrl;
  @Value("${dtsso-security.oauth2.client.user-info-uri}")
  private String userInfoUrl;

  @Value("${dtsso-security.oauth2.defaultUserInfo.rolesIds}")
  private String defaultRolesIds;
  @Value("${dtsso-security.oauth2.defaultUserInfo.companyId}")
  private String defaultCompanyId;
  @Value("${dtsso-security.oauth2.defaultUserInfo.deptId}")
  private String defaultDeptId;
  @Value("${dtsso-security.oauth2.defaultUserInfo.deptPostId}")
  private String defaultDeptPostId;

  @Resource
  TmptAuthUserBizServiceImpl tmptAuthUserService;

  @GetMapping("/getAccessToken/{code}")
  public Result getAccessToken(@PathVariable("code") String code) {
    // 去SSO取access token
    HashMap<String, Object> paramMap = new HashMap<>();
    paramMap.put("client_id", clientId);
    paramMap.put("client_secret", clientSecret);
    log.info("redirectUri =================>" + redirectUri);
    paramMap.put("redirect_uri", redirectUri);
    paramMap.put("grant_type", "authorization_code");
    paramMap.put("code", code);

    String result = HttpUtil.post(accessTokenUrl, paramMap);
    log.info("accessTokenUrl =================>" + result);
    paramMap = new HashMap<>();
    paramMap.put("access_token", JSONUtil.parseObj(result).getStr("access_token"));
    paramMap.put("isAdUser", 1);
    JSONObject resultObject = JSONUtil.parseObj(HttpUtil.get(userInfoUrl, paramMap), true);

    log.info("userInfoUrl =================>" + resultObject.toString());
    if (!"success".equals(resultObject.getStr("msg"))) {
      throw new RuntimeException("认证失败");
    }

    Map<String, Object> userInfo = resultObject.getJSONObject("data");
    String uuid = (String) userInfo.get("user_uuid");
    String mobile = (String) userInfo.get("mobile");
    String realname = userInfo.get("realname")==null?"":userInfo.get("realname").toString();
    String email = userInfo.get("email")==null?"":userInfo.get("email").toString();
    if (StringUtils.isNull(mobile)) {
      return Result.builder().fault("手机号不能为空");
    }

    // 不存在，先自动注册
    A2UserDto a2UserDto = menuService.getUserByLoginname(mobile);
    if (a2UserDto==null) {
      TmptAuthUserBizDto userBizDto = new TmptAuthUserBizDto();
      userBizDto.setLoginname(mobile);
      userBizDto.setPasswordBcrypt(DateTool.getCurTimestamp()+"");
      userBizDto.setRoleIds(defaultRolesIds); //默认
      userBizDto.setCompanyId(Long.parseLong(defaultCompanyId));  //默认
      userBizDto.setTmptAuthDeptId(Integer.parseInt(defaultDeptId));  //默认
      userBizDto.setTmptAuthDeptPostId(Long.parseLong(defaultDeptPostId)); //默认
      userBizDto.setClientId(uuid);
      userBizDto.setName(StringUtils.isNull(realname)||realname.equalsIgnoreCase("null")?mobile:realname);
      userBizDto.setEmail(email);
      userBizDto.setPhone(mobile);
      userBizDto.setCreateman("oss");
      Result<TmptAuthUserBizDto> result1 = tmptAuthUserService.create(userBizDto);
      if (!result1.isSuccess()) return result1;
      a2UserDto = menuService.getUserByLoginname(mobile);
    }

    Map<String, Object> token = getToken(mobile, a2UserDto.getPasswordBcrypt());
    return Result.builder(token);
  }


  private Map<String, Object> getToken(String username, String password){
    // 取当前服务端口
    String url = "http://scm-epcodeless-core/core/oauth/token";
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
    MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
    map.add("username", username);
    map.add("pswd", password);
    map.add("request_from", "innerService");
    map.add("grant_type", "password");
    map.add("client_id", "mengxuegu-pc");
    map.add("client_secret", "mengxuegu-secret");

    HttpEntity<MultiValueMap<String, String>> request1 = new HttpEntity<>(map, headers);
    Result result = restTemplate.postForObject(url, request1, Result.class);
    return result.getMap();
  }

}
